001 /*
002 * Copyright 2005 Stephen J. McConnell
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
013 * implied.
014 *
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package net.dpml.tools.tasks;
020
021 import java.io.File;
022 import java.io.OutputStream;
023 import java.io.FileOutputStream;
024 import java.io.OutputStreamWriter;
025 import java.io.Writer;
026 import java.net.URI;
027
028 import net.dpml.lang.Version;
029
030 import net.dpml.library.Module;
031 import net.dpml.library.Resource;
032 import net.dpml.library.Type;
033
034 import net.dpml.transit.Artifact;
035 import net.dpml.transit.link.ArtifactLinkManager;
036
037 import org.apache.tools.ant.BuildException;
038 import org.apache.tools.ant.Project;
039 import org.apache.tools.ant.types.FileSet;
040 import org.apache.tools.ant.taskdefs.Copy;
041
042 /**
043 * Execute the install phase.
044 *
045 * @author <a href="http://www.dpml.net">The Digital Product Meta Library</a>
046 * @version 1.0.0
047 */
048 public class InstallTask extends GenericTask
049 {
050 /**
051 * Execute the project.
052 * @exception BuildException if a build errror occurs
053 */
054 public void execute() throws BuildException
055 {
056 installDeliverables();
057 }
058
059 private void installDeliverables()
060 {
061 Resource resource = getResource();
062 Type[] types = resource.getTypes();
063 if( types.length == 0 )
064 {
065 return;
066 }
067
068 final File deliverables = getContext().getTargetDeliverablesDirectory();
069 for( int i=0; i < types.length; i++ )
070 {
071 Type type = types[i];
072
073 //
074 // Check that the project has actually built the resource
075 // type that it declares
076 //
077
078 String id = type.getID();
079 String filename = getContext().getLayoutFilename( id );
080 File group = new File( deliverables, id + "s" );
081 File target = new File( group, filename );
082 if( !target.exists() && !id.equalsIgnoreCase( "null" ) )
083 {
084 final String error =
085 "Project ["
086 + resource
087 + "] declares that it produces the resource type ["
088 + id
089 + "] however no artifacts of that type are present in the target deliverables directory.";
090 throw new BuildException( error, getLocation() );
091 }
092
093 //
094 // If the type declares an alias then construct a link
095 // and add the link to the deliverables directory as part of
096 // install process.
097 //
098
099 Version version = type.getVersion();
100 if( null != version )
101 {
102 try
103 {
104 Artifact artifact = resource.getArtifact( id );
105 String uri = artifact.toURI().toASCIIString();
106
107 String link = null;
108 if( Version.NULL_VERSION.equals( version ) )
109 {
110 link = resource.getName() + "." + id + ".link";
111 }
112 else
113 {
114 link = resource.getName()
115 + "-"
116 + version.getMajor()
117 + "."
118 + version.getMinor()
119 + "."
120 + id + ".link";
121 }
122 File out = new File( group, link );
123 boolean flag = true;
124 if( out.exists() )
125 {
126 ArtifactLinkManager manager = new ArtifactLinkManager();
127 URI enclosed = manager.getTargetURI( new URI( out.toURL().toString() ) );
128 if( artifact.toURI().equals( enclosed ) )
129 {
130 flag = false;
131 }
132 }
133
134 if( flag )
135 {
136 log( link.toString() );
137 log( uri.toString() );
138 out.createNewFile();
139 final OutputStream output = new FileOutputStream( out );
140 final Writer writer = new OutputStreamWriter( output );
141 writer.write( uri );
142 writer.close();
143 output.close();
144 }
145 }
146 catch( Exception e )
147 {
148 final String error =
149 "Internal error while attempting to create a link for the resource type ["
150 + id
151 + "] in project ["
152 + resource
153 + "].";
154 throw new BuildException( error, e, getLocation() );
155 }
156 }
157 }
158
159 if( deliverables.exists() )
160 {
161 log( "Installing deliverables from [" + deliverables + "]", Project.MSG_VERBOSE );
162 final File cache = (File) getProject().getReference( "dpml.cache" );
163 log( "To cache dir [" + cache + "]", Project.MSG_VERBOSE );
164 try
165 {
166 final FileSet fileset = new FileSet();
167 fileset.setProject( getProject() );
168 fileset.setDir( deliverables );
169 fileset.createInclude().setName( "**/*" );
170 Module parent = resource.getParent();
171 if( null == parent )
172 {
173 copy( cache, fileset, true );
174 }
175 else
176 {
177 final String group = parent.getResourcePath();
178 final File destination = new File( cache, group );
179 copy( destination, fileset, true );
180 }
181 }
182 catch( Throwable e )
183 {
184 final String error =
185 "Unexpected error while constructing ant fileset."
186 + "\nDeliverables dir: " + deliverables;
187 throw new BuildException( error, e );
188 }
189 }
190 }
191
192 /**
193 * Utility operation to copy a fileset to a destination directory.
194 * @param destination the destination directory
195 * @param fileset the fileset to copy
196 * @param preserve the preserve timestamp flag
197 */
198 public void copy( final File destination, final FileSet fileset, boolean preserve )
199 {
200 mkDir( destination );
201 final Copy copy = (Copy) getProject().createTask( "copy" );
202 copy.setTaskName( getTaskName() );
203 copy.setPreserveLastModified( preserve );
204 copy.setTodir( destination );
205 copy.addFileset( fileset );
206 copy.setOverwrite( true ); // required for filtered deliverables
207 copy.init();
208 copy.execute();
209 }
210 }